<template>
  <div :class="{'is-fullscreen': isFullscreen}" class="view-design d-layout-container d-layout-container-nofooter d-layout-container-dark">
    <div :class="isShowActions ? 'is-actions-active' : ''" class="design-header d-layout-header">
      <a @click="isShowActions = !isShowActions" class="design-actions-switch" href="javascript:void(0)">
        <i class="el-icon-s-tools"></i>
      </a>
      <div class="design-actions">
        <slot name="actions-before"></slot>
        <el-select v-if="isShowLayout" @change="handleChageLayout" v-model="stock.state.page.meta.name" placeholder="切换布局" size="mini">
          <el-option
            v-for="item in stock.state.layoutCollection"
            :key="item.name"
            :label="item.text"
            :value="item.name">
          </el-option>
        </el-select>
        <el-button v-if="isShowFullscreen" @click="handleFullScreen" icon="el-icon-full-screen" size="mini">全屏</el-button>
        <FileChooser v-if="isShowImport" @change="handleImport" :button="{icon:'el-icon-upload2',size:'mini'}" text="导入" accept="	application/json" title="导入页面配置元文件" />
        <el-button v-if="isShowExport" @click="handleExport" icon="el-icon-download" size="mini" title="导出当前页面配置元文件">导出</el-button>
        <el-button @click="handleShowLayoutProperty" size="mini" title="打开容器属性面板">容器属性</el-button>
        <Switcher v-if="isShowComponent" v-model="isExpandSide" labelOn="组件" labelOff="组件" size="xs" title="打开或关闭组件面板" />
        <Switcher v-if="isShowProperty" v-show="stock.state.layoutPropertyView" v-model="isExpandProp" labelOn="属性" labelOff="属性" size="xs" title="打开或关闭属性面板" />
        <Switcher v-if="isShowThrough" v-model="isThrough" labelOn="穿透" labelOff="穿透" size="xs" title="隐藏或显示组件实例遮罩层,打开可触发组件相应事件" />
        <el-button v-if="isShowCompile && !isCompile" @click="handleCompile" icon="el-icon-cpu" size="mini" type="primary" title="手动编译组件代码">编译</el-button>
        <Switcher v-if="isShowCompile" v-model="isCompile" labelOn="编译" labelOff="编译" size="xs" title="自动编译,打开则修改代码时自动编译并渲染视图" />
        <slot name="actions-after"></slot>
      </div>
      <slot name="header"></slot>
    </div>
    <div :class="{'design-body-through': isThrough}" class="design-body d-bg-fog">
      <div
        :class="{'design-side-collapse': !isExpandSide}"
        class="design-side">
        <DComponents :stock="stock" />
      </div>
      <div
        v-show="stock.state.layoutPropertyView"
        :class="{'design-property-collapse': !isExpandProp, 'design-property-fullscreen': stock.state.isPropertyPanelFull}"
        class="design-property" ref="dpropertyContainer">
        <DProperty :stock="stock" ref="dproperty" />
        <span @mousedown="handowDownCollapse" @touchstart="handowDownCollapse" class="design-collpase-bar" title="拖拽改变属性面板宽度">
          <MoreIcon class="bar-icon" />
        </span>
      </div>
      <div class="design-render d-layout-content">
        <DRender v-if="isShowRender" :stock="stock" ref="drender" />
      </div>
    </div>
  </div>
</template>

<script>
import Vue from 'vue'
import { Switcher } from '@daelui/vdog/dist/components.js'
import { MoreIcon } from '@daelui/vdog/dist/icons.js'
import { filer, parser } from '@daelui/dogjs/dist/components.js'
import FileChooser from '@/components/uploader/file-chooser.vue'
import DComponents from './dcomponents.vue'
import DRender from './drender.vue'
import DProperty from './dproperty.vue'
import stock from '@/service/stock/index'

export default {
  name: 'designer',

  components: {
    Switcher,
    MoreIcon,
    FileChooser,
    DComponents,
    DRender,
    DProperty
  },

  props: {
    isShowLayout: {
      type: Boolean,
      default: false
    },
    isShowFullscreen: {
      type: Boolean,
      default: true
    },
    isShowImport: {
      type: Boolean,
      default: true
    },
    isShowExport: {
      type: Boolean,
      default: true
    },
    isShowComponent: {
      type: Boolean,
      default: true
    },
    isShowProperty: {
      type: Boolean,
      default: true
    },
    isShowThrough: {
      type: Boolean,
      default: true
    },
    isShowCompile: {
      type: Boolean,
      default: true
    },
    stock: {
      type: Object,
      default () {
        return stock
      }
    }
  },

  computed: {
    isCompile: {
      get () {
        return stock.state.isCompile
      },
      set (val) {
        let isCompile = val ? '1' : '0'
        if (window.sessionStorage) {
          sessionStorage.setItem('designer-is-compile', isCompile)
        }
        return stock.state.isCompile = val
      }
    }

  },

  data () {
    return {
      activeIndex: '1',
      isShowActions: false,
      isFullscreen: false,
      isExpandSide: true,
      isExpandProp: true,
      isThrough: false,
      isShowRender: true
    }
  },

  watch: {
    isExpandSide () {
      this.updateView()
    },
    isExpandProp () {
      this.updateView()
    },
    isCompile () {
      this.$triggerEvent('update-is-compile', this.isCompile)
    }
  },

  methods: {
    // 初始化
    init () {
      // 进入设计态
      this.stock.state.isDesign = true
      this.$bindEvent('init-is-compile', (callback) => {
        if (typeof callback === 'function') {
          callback(this.isCompile)
        }
      })
    },

    // 设置布局列表
    setLayoutCollection (list) {
      this.stock.setter.setLayoutCollection(list)
    },
    // 设置组件列表
    setComponentCollection (list) {
      this.stock.setter.setComponentCollection(list)
    },
    // 设置页面数据
    setPageState (page) {
      this.stock.state.page = page
    },

    // 插入组件
    handleInsertComponent (component) {
      this.stock.setter.insertComponent(component)
    },

    /**
     * @function 获取元数据
    */
    getMetaValue () {
      return this.$refs.drender.getMetaValue()
    },

    handleSelect () {},

    /**
     * @function 更新视图
    */
    updateView () {
      this.$refs.drender.updateView()
    },

    // 全屏
    handleFullScreen () {
      if (document.documentElement.RequestFullScreen) {
        document.documentElement.RequestFullScreen()
      }
      // 兼容火狐
      if(document.documentElement.mozRequestFullScreen){
        document.documentElement.mozRequestFullScreen()
      }
      // 兼容谷歌等可以webkitRequestFullScreen也可以webkitRequestFullscreen
      if(document.documentElement.webkitRequestFullScreen){
        document.documentElement.webkitRequestFullScreen()
      }
      // 兼容IE,只能写msRequestFullscreen
      if (document.documentElement.msRequestFullscreen) {
        document.documentElement.msRequestFullscreen()
      }
    },

    onFullscreen () {
      this.isFullscreen = !this.isFullscreen
    },

    // 导入
    handleImport (files) {
      files = Array.isArray(files) ? files : []
      let file = files[0]
      if (file) {
        filer.readFileText(file.file).then(text => {
          let data = parser.toObject(text, true) || {}
          if (data && data.meta) {
            this.stock.state.page = data
          }
        }).catch(() => {
          this.$message({
            message: '解析失败',
            type: 'error',
            showClose: true
          })
        })
      } else {
        this.$message({
          message: '未读取到文件',
          type: 'warning',
          showClose: true
        })
      }
    },

    // 导出
    handleExport () {
      let page = this.stock.state.page
      page.meta = this.getMetaValue()
      let content = parser.stringify(page, null, '  ')
      filer.downloadFile(this.trimSpecial((page.name || page.code || Date.now())) + '.json', content)
    },
    // 清除特殊字符
    trimSpecial (string) {
      //替换字符串中的所有特殊字符（包含空格）
      if (string !== '') {
        const pattern = /[`~!@#$^\-&*()=|{}':;',\\\[\]\.<>\/?~！@#￥……&*（）——|{}【】'；：""'。，、？\s]/g
        string = string.replace(pattern, '')
      }
      return string
    },

    // 修改布局
    handleChageLayout () {
      this.isShowRender = false
      setTimeout(() => {
        this.isShowRender = true
      }, 100)
    },

    // 显示容器属性
    handleShowLayoutProperty () {
      this.$refs.drender.$refs.render.$refs.view.handleSelectLayout()
      this.isExpandProp = true
    },
    // 属性侧边栏伸缩
    handowDownCollapse (e) {
      mousedown(e, this.$refs.dpropertyContainer)
    },

    // 编译组件
    handleCompile () {
      this.$triggerEvent('compile-page-item')
    }
  },

  beforeCreate () {
    // 全局事件
    const vbus = new Vue()
    Vue.prototype.$bindEvent = Vue.prototype.$bindEvent || function (name, callback) {
      vbus.$on(name, callback)
    }
    Vue.prototype.$triggerEvent = Vue.prototype.$triggerEvent || function (name, data) {
      vbus.$emit(name, data)
    }
    Vue.prototype.$unbindEvent = Vue.prototype.$unbindEvent || function (name, callback) {
      vbus.$off(name, callback)
    }
  },

  beforeMount () {
    if (window.sessionStorage) {
      let isCompile = sessionStorage.getItem('designer-is-compile')
      isCompile = isCompile !== '0' ? true : false
      this.isCompile = isCompile
    }
    this.init()
  },

  mounted () {
    this.triggerFullscreen = this.onFullscreen.bind(this)
    let events = ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange']
    events.forEach((item) => {
      window.addEventListener(item, this.triggerFullscreen, false)
    })
  },

  beforeDestroy() {
    let events = ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange']
    events.forEach((item) => {
      window.removeEventListener(item, this.triggerFullscreen)
    })
  },

  stock
}

export {
  stock
}

// 按下
function mousedown (e, el) {
  e = e.touches ? e.touches[0] : e
  let elStyle = getComputedStyle(el)
  let bodyStyle = getComputedStyle(document.body)
  document.collaseActive = {
    e, el,
    elStyle: { width: parseFloat(elStyle.width) },
    bodyStyle: { width: parseFloat(bodyStyle.width) }
  }
  document.addEventListener('mousemove', mousemove, false)
  document.addEventListener('touchmove', mousemove, false)
  document.addEventListener('mouseup', mouseup, false)
  document.addEventListener('touchend', mouseup, false)
}

// 移动
function mousemove (e) {
  e = e.touches ? e.touches[0] : e
  let act = document.collaseActive
  if (act && act.e && act.el) {
    let lastX = act.e.clientX
    let currentX = e.clientX
    let width = act.elStyle.width
    width = width - (currentX - lastX)
    let min = 24
    let max = act.bodyStyle.width - 168
    if (width < min) {
      width = min
    }
    // 大于左侧加min * 2
    else if (width > max) {
      width = max
    }
    act.el.style.width = width + 'px'
  }
}

// 按起
function mouseup () {
  document.collaseActive = null
  document.removeEventListener('mousemove', mousemove)
  document.removeEventListener('mouseup', mouseup)
}
</script>

<style lang="less" scoped>
.view-design {
  overflow: hidden;
  width: 100%;
  &.is-fullscreen {
    .design-header {
      display: none;
    }
    .design-body {
      height: calc(100vh);
    }
  }
  .design-body-through {
    /deep/ .d-drag-resizer {
      &:before {
        display: none;
      }
    }
    /deep/ .d-dr-de-nesw {
      display: none;
    }
  }
  .design-body {
    height: calc(100vh - 48px);
    &:after {
      content: "";
      display: block;
      clear: both;
    }
  }
  .design-side {
    float: left;
    position: relative;
    overflow: visible;
    width: 168px;
    height: 100%;
    z-index: 11;
    border-right: 1px solid #eee;
    .item-component {
      cursor: pointer;
    }
    .component-name {
      text-align: center;
    }
  }
  .design-side-collapse {
    width: 0;
    /deep/.components-paner {
      overflow: hidden;
      width: 0;
    }
  }
  .design-render {
    overflow: auto;
    height: 100%;
    background:#ddd;
    background-image: linear-gradient(white 0px,transparent 0),
    linear-gradient(90deg, white 0px,transparent 0),
    linear-gradient(hsla(0,0%,100%,.6) 1px,transparent 0),
    linear-gradient(90deg,hsla(0,0%,100%,.6) 1px,transparent 0);
    background-size: 64px 64px, 64px 64px, 64px 16px, 64px 16px;
  }
  @width: 512px;
  .design-property {
    float: right;
    position: relative;
    overflow: auto;
    width: @width;
    height: 100%;
    z-index: 11;
  }
  .design-property-collapse {
    width: 0 !important;
    /deep/.property-paner {
      overflow: hidden;
      width: 0 !important;
    }
  }
  .design-collpase-bar {
    position: absolute;
    left: 0;
    top: 50%;
    .bar-icon {
      font-size: 24px;
      transform: rotate(90deg);
      color: #409EFF;
      cursor: ew-resize;
    }
  }
}
</style>

<style lang="less">
.design-menus {
  float: left;
  width: 33%;
  &.el-menu--horizontal>.el-menu-item {
    height: 48px;
    line-height: 48px;
  }
  &.el-menu--horizontal>.el-submenu .el-submenu__title {
    height: 48px;
    line-height: 48px;
  }
}
.el-tabs-paner {
  .el-tabs__header {
    margin-bottom: 0;
  }
  .el-tabs__nav {
    margin-left: 16px;
  }
  .el-collapse-item__wrap {
    padding-top: 8px;
    background: #f2f2f7;
  }
  .el-collapse-item__content {
    padding-bottom: 8px;
  }
}
.design-header {
  .design-name {
    float: left;
    display: flex;
    align-items: center;
    padding-left: 8px;
    height: 100%;
  }
  .design-actions {
    float: right;
    display: flex;
    height: 100%;
    align-items: center;
    padding-right: 8px;
    & > .d-btn,
    & > .d-switch-slider,
    & > .d-file-chooser,
    & > .d-form-switch,
    & > .el-dropdown,
    & > .el-button {
      margin-left: 8px;
    }
    .el-button--mini,
    .el-button--mini.is-round {
      padding: 7px 10px;
    }
  }
}
.design-property-fullscreen {
  .property-paner {
    overflow: hidden;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 3;
    & + .design-collapse-prop {
      display: none;
    }
    .d-editor-monaco {
      height: calc(100vh - 94px) !important;
    }
  }
  & + .design-render {
    position: relative;
    z-index: 2;
  }
}
.design-actions-switch {
  display: none;
}

@media (max-width: 980px) {
  .design-header {
    &.is-actions-active {
      z-index: 13;
      .design-actions {
        display: flex;
      }
    }
    .design-actions {
      display: none;
      overflow: auto;
      position: absolute;
      right: 0;
      top: 48px;
      flex-direction: column;
      box-sizing: border-box;
      padding: 8px;
      width: 108px;
      height: calc(100vh - 48px);
      background: rgba(0, 0, 0, 0.5);
      & > .el-button,.d-file-chooser {
        flex-shrink: 0;
        display: block;
        margin: 4px 0;
        width: 100%;
      }
      .d-form-switch {
        flex-shrink: 0;
        display: block;
        margin: 4px 0;
      }
      .d-file-chooser .el-button {
        display: block;
        width: 100%;
      }
      .el-dropdown {
        flex-shrink: 0;
        margin: 4px 0;
      }
    }
    .design-actions-switch {
      display: block;
      float: right;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 36px;
      height: 48px;
      font-size: 20px;
      color: #fff;
      text-decoration: none;
      &:focus,&:active {
        text-decoration: none;
      }
    }
  }
  .design-property-fullscreen .property-paner {
    top: 48px;
  }
  .view-design  {
    .design-body {
      .design-property {
        width: 50vw;
      }
    }
  }
}
</style>
